/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.editor;
import java.awt.event.ActionEvent;
import java.util.Iterator;
import java.util.List;
import javax.swing.text.JTextComponent;
import javax.swing.text.BadLocationException;
import javax.swing.text.TextAction;
import javax.swing.text.Segment;
/**
* Various internal tests
*
* @author Miloslav Metelka
* @version 0.10
*/
public class EditorDebug {
private EditorDebug() {
// instance creation has no sense
}
public static void dumpPlanes(JTextComponent component) {
BaseDocument doc = (BaseDocument)component.getDocument();
Class markClasses[] = new Class[] {
MarkFactory.LineMark.class,
MarkFactory.CaretMark.class,
MarkFactory.DrawMark.class,
MarkFactory.SyntaxMark.class,
Mark.class
};
char markChars[] = new char[] {
'L', 'C', 'D', 'S', 'B'
};
System.out.println("--------------------------- DUMP OF MARK PLANES --------------------------------"); // NOI18N
System.out.println("Mark legend:\nD - DrawMark\n" // NOI18N
+ "S - SyntaxMark\nB - BaseMark\n" // NOI18N
+ "L - LineMark\nC - CaretMark"); // NOI18N
System.out.println(doc.op.markPlanesToString(markClasses, markChars));
System.out.println("--------------------------------------------------------------------------------\n"); // NOI18N
}
public static void dumpSyntaxMarks(JTextComponent component) {
System.out.println("--------------------------- DUMP OF SYNTAX MARKS --------------------------------"); // NOI18N
final BaseDocument doc = (BaseDocument)component.getDocument();
final int docLen = doc.getLength();
doc.op.renderMarks(
new DocMarks.Renderer() {
public void render() {
int markCnt = getMarkCnt();
int index = 0;
int pos = 0;
int lastPos = pos;
int lineCnt = 0;
int lastMarkPos = 0;
int maxMarkDistance = 0;
int minMarkDistance = docLen;
Mark markArray[] = getMarkArray();
SyntaxSeg.Slot slot = SyntaxSeg.getFreeSlot();
Syntax syntax = doc.getFreeSyntax();
try {
syntax.load(null, slot.array, 0, 0, false);
while (index < markCnt) {
Mark mark = markArray[index++];
pos += getRelPos(mark);
if (mark instanceof MarkFactory.SyntaxMark) {
MarkFactory.SyntaxMark syntaxMark = (MarkFactory.SyntaxMark)mark;
int delta = pos - lastMarkPos;
if (delta > maxMarkDistance) {
maxMarkDistance = delta;
}
if (delta < minMarkDistance) {
minMarkDistance = delta;
}
lastMarkPos = pos;
int preScan = syntax.getPreScan();
int loadPos = lastPos - preScan;
int scanLen = pos - loadPos;
try {
slot.load(doc, loadPos, scanLen);
} catch (BadLocationException e) {
e.printStackTrace();
}
syntax.relocate(slot.array, slot.offset + preScan, scanLen - preScan, (pos == docLen));
while (true) {
int tokenID = syntax.nextToken();
if (tokenID == Syntax.EOT) {
break;
}
if (tokenID == Syntax.EOL) {
lineCnt++;
}
}
lastPos = pos;
try {
System.out.println(((syntaxMark == doc.op.eolMark)
? "!!EOLMark!!" : "syntaxMark:") // NOI18N
+ " getOffset()=" + Utilities.debugPosition(doc, syntaxMark.getOffset()) // NOI18N
+ ", getLine()=" + syntaxMark.getLine() // NOI18N
+ ", " + syntaxMark // NOI18N
+ ",\n StateInfo=" + syntaxMark.getStateInfo() // NOI18N
+ ",\n Syntax:" + syntax); // NOI18N
} catch (InvalidMarkException e) {
e.printStackTrace();
}
}
}
} finally {
doc.releaseSyntax(syntax);
SyntaxSeg.releaseSlot(slot);
}
System.out.println("Maximum mark distance is " + maxMarkDistance // NOI18N
+ "\nMinimum mark distance is " + minMarkDistance); // NOI18N
}
}
);
System.out.println("--------------------------------------------------------------------------------\n"); // NOI18N
}
public static void test(JTextComponent component) {
BaseTextUI ui = ((BaseTextUI)component.getUI());
BaseView view = (BaseView)ui.getRootView(component);
view = (BaseView)view.getView(0);
final BaseDocument doc = (BaseDocument)component.getDocument();
ExtUI extUI = ui.getExtUI();
final int docLen = doc.getLength();
System.out.println("\n------------------------- Registry --------------------------------"); // NOI18N
System.out.println(Registry.getRegistry().toString());
System.out.println("\n------------------------- DEBUGGING INFORMATION --------------------------------"); // NOI18N
String buf = "Document: " + doc // NOI18N
+ "\nview.mainHeight=" + ((LeafView)view).mainHeight // NOI18N
+ "\nDoubleBuffering=" + component.isDoubleBuffered(); // NOI18N
buf += "\ncomponent.getLocation()=" + component.getLocation() // NOI18N
+ "\ncomponent.getSize()=" + component.getSize() // NOI18N
+ "\nvirtualSize=" + extUI.virtualSize; // NOI18N
buf += "\nExtUI LAYERS:\n" + extUI.getDrawLayerList(); // NOI18N
System.out.println(buf);
System.out.println(doc.op.infoToString());
buf = "\n-------------------------- EOL Test -------------------------------\n"; // NOI18N
try {
int lineCnt1 = doc.op.getLine(doc.getLength());
buf += "Number of lines by getLine()=" + lineCnt1; // NOI18N
final int lineCnt2[] = new int[1];
System.out.println(buf);
doc.op.renderMarks(
new DocMarks.Renderer() {
public void render() {
int markCnt = getMarkCnt();
int index = 0;
int pos = 0;
int lastPos = pos;
int lineCnt = 0;
Mark markArray[] = getMarkArray();
SyntaxSeg.Slot slot = SyntaxSeg.getFreeSlot();
Syntax syntax = doc.getFreeSyntax();
try {
syntax.load(null, slot.array, 0, 0, false);
while (index < markCnt) {
Mark mark = markArray[index++];
pos += getRelPos(mark);
if (mark instanceof MarkFactory.SyntaxMark) {
MarkFactory.SyntaxMark syntaxMark = (MarkFactory.SyntaxMark)mark;
int preScan = syntax.getPreScan();
int loadPos = lastPos - preScan;
int scanLen = pos - loadPos;
try {
slot.load(doc, loadPos, scanLen);
} catch (BadLocationException e) {
e.printStackTrace();
}
syntax.relocate(slot.array, slot.offset + preScan, scanLen - preScan, (pos == docLen));
while (true) {
int tokenID = syntax.nextToken();
if (tokenID == Syntax.EOT) {
break;
}
if (tokenID == Syntax.EOL) {
lineCnt++;
}
}
lastPos = pos;
try {
if (mark.getLine() != lineCnt) {
System.out.println("Error found comparing line at mark with index=" // NOI18N
+ (index - 1) + " having pos=" + pos // NOI18N
+ ". Line offset stored in mark is " + mark.getLine() // NOI18N
+ " but syntax scanning gives " + lineCnt + ". Scanned area" // NOI18N
+ " with preScan=" + preScan + " is " + scanLen + " long: '" // NOI18N
+ debugChars(slot.array, slot.offset, scanLen)
+ "'. The line test was interrupted."); // NOI18N
break;
}
} catch (InvalidMarkException e) {
e.printStackTrace();
}
}
}
lineCnt2[0] = lineCnt;
} finally {
doc.releaseSyntax(syntax);
SyntaxSeg.releaseSlot(slot);
}
}
}
);
buf = "Number of lines by syntax scanning=" + lineCnt2[0] + "\n"; // NOI18N
buf += (lineCnt1 == lineCnt2[0]) ? "Line counting test succeeded." // NOI18N
: "Line counting test failed !"; // NOI18N
System.out.println(buf);
} catch (BadLocationException e) {
e.printStackTrace();
}
buf = "\n------------------------ CR occurence test ------------------------\n"; // NOI18N
try {
char chars[] = doc.getChars(0, docLen);
int i;
for (i = 0; i < docLen; i++) {
if (chars[i] == '\r') {
buf += "CR found at pos=" + i + ", line=" + doc.op.getLine(i) + "\n"; // NOI18N
break;
}
}
if (i == docLen) {
buf += "No CR found. CR occurence test suceeded."; // NOI18N
}
} catch (BadLocationException e) {
e.printStackTrace();
}
System.out.println(buf);
}
static class DumpPlanesAction extends TextAction {
static final long serialVersionUID =-6845202263936980798L;
DumpPlanesAction() {
super(BaseKit.dumpPlanesAction);
}
public void actionPerformed(ActionEvent evt) {
JTextComponent component = getTextComponent(evt);
dumpPlanes(component);
}
}
static class DumpSyntaxMarksAction extends TextAction {
static final long serialVersionUID =-5416690898412332655L;
DumpSyntaxMarksAction() {
super(BaseKit.dumpSyntaxMarksAction);
}
public void actionPerformed(ActionEvent evt) {
JTextComponent component = getTextComponent(evt);
dumpSyntaxMarks(component);
}
}
static class SelfTestAction extends TextAction {
static final long serialVersionUID =4317494489421553541L;
SelfTestAction() {
super(BaseKit.selfTestAction);
}
public void actionPerformed(ActionEvent evt) {
JTextComponent component = getTextComponent(evt);
test(component);
}
}
public static void checkSettings(Class kitClass) throws Error {
int readBufferSize = SettingsUtil.getInteger(kitClass, Settings.READ_BUFFER_SIZE,
DefaultSettings.defaultReadBufferSize);
int writeBufferSize = SettingsUtil.getInteger(kitClass, Settings.WRITE_BUFFER_SIZE,
DefaultSettings.defaultWriteBufferSize);
int readMarkDistance = SettingsUtil.getInteger(kitClass, Settings.READ_MARK_DISTANCE,
DefaultSettings.defaultReadMarkDistance);
int markDistance = SettingsUtil.getInteger(kitClass, Settings.MARK_DISTANCE,
DefaultSettings.defaultMarkDistance);
int maxMarkDistance = SettingsUtil.getInteger(kitClass, Settings.MAX_MARK_DISTANCE,
DefaultSettings.defaultMaxMarkDistance);
int minMarkDistance = SettingsUtil.getInteger(kitClass, Settings.MIN_MARK_DISTANCE,
DefaultSettings.defaultMinMarkDistance);
int syntaxUpdateBatchSize = SettingsUtil.getInteger(kitClass, Settings.SYNTAX_UPDATE_BATCH_SIZE,
DefaultSettings.defaultSyntaxUpdateBatchSize);
// Now perform checks
if (maxMarkDistance < markDistance) {
throw new Error("maxMarkDistance=" + maxMarkDistance // NOI18N
+ " < markDistance=" + markDistance); // NOI18N
}
if (markDistance < minMarkDistance) {
throw new Error("markDistance=" + markDistance // NOI18N
+ " < minMarkDistance=" + minMarkDistance); // NOI18N
}
if (readMarkDistance < minMarkDistance) {
throw new Error("readMarkDistance=" + readMarkDistance // NOI18N
+ " < minMarkDistance=" + minMarkDistance); // NOI18N
}
if (syntaxUpdateBatchSize < maxMarkDistance) {
throw new Error("syntaxUpdateBatchSize=" + syntaxUpdateBatchSize // NOI18N
+ " < maxMarkDistance=" + maxMarkDistance); // NOI18N
}
}
/** Replace '\n', '\r' and '\t' in the string so they are identifiable. */
public static String debugString(String s) {
return debugChars(s.toCharArray(), 0, s.length());
}
public static String debugChars(Segment seg) {
return debugChars(seg.array, seg.offset, seg.count);
}
public static String debugChars(char chars[]) {
return debugChars(chars, 0, chars.length);
}
/** Replace '\n', '\r' and '\t' in the char array so they are identifiable. */
public static String debugChars(char chars[], int offset, int len) {
if (len < 0) {
return "EditorDebug.debugChars() !ERROR! len=" + len + " < 0"; // NOI18N
}
if (offset < 0) {
return "EditorDebug.debugChars() !ERROR! offset=" + offset + " < 0"; // NOI18N
}
if (offset + len > chars.length) {
return "EditorDebug.debugChars() !ERROR! offset=" + offset + " + len=" + len // NOI18N
+ " > chars.length=" + chars.length; // NOI18N
}
StringBuffer sb = new StringBuffer(len);
int endOffset = offset + len;
for (; offset < endOffset; offset++) {
switch (chars[offset]) {
case '\n':
sb.append("\\n"); // NOI18N
break;
case '\t':
sb.append("\\t"); // NOI18N
break;
case '\r':
sb.append("\\r"); // NOI18N
break;
default:
sb.append(chars[offset]);
}
}
return sb.toString();
}
public static String debugPairs(int[] pairs) {
String ret;
if (pairs == null) {
ret = "Null pairs"; // NOI18N
} else if (pairs.length == 0) {
ret = "No pairs"; // NOI18N
} else {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < pairs.length; i += 2) {
sb.append('[');
sb.append(pairs[i]);
sb.append(", "); // NOI18N
sb.append(pairs[i + 1]);
if (i < pairs.length - 1) {
sb.append("]\n"); // NOI18N
}
}
ret = sb.toString();
}
return ret;
}
public static String debugArray(Object[] array) {
String ret;
if (array == null) {
ret = "Null array"; // NOI18N
} else if (array.length == 0) {
ret = "Empty array"; // NOI18N
} else {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < array.length; i++) {
sb.append('[');
sb.append(i);
sb.append("]="); // NOI18N
sb.append(array[i]);
if (i != array.length - 1) {
sb.append('\n');
}
}
ret = sb.toString();
}
return ret;
}
public static String debugArray(int[] array) {
String ret;
if (array == null) {
ret = "Null array"; // NOI18N
} else if (array.length == 0) {
ret = "Empty array"; // NOI18N
} else {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < array.length; i++) {
sb.append('[');
sb.append(i);
sb.append("]="); // NOI18N
sb.append(array[i]);
if (i != array.length - 1) {
sb.append('\n');
}
}
ret = sb.toString();
}
return ret;
}
public static String debugBlocks(BaseDocument doc, int[] blocks) {
String ret;
if (blocks == null) {
ret = "Null blocks"; // NOI18N
} else if (blocks.length == 0) {
ret = "Empty blocks"; // NOI18N
} else if (blocks.length % 2 != 0) {
ret = "Blocks.length=" + blocks.length + " is not even!"; // NOI18N
} else {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < blocks.length; i += 2) {
sb.append('[');
sb.append(i);
sb.append("]=("); // NOI18N
sb.append(blocks[i]);
sb.append(", "); // NOI18N
sb.append(blocks[i + 1]);
sb.append(") or ("); // NOI18N
sb.append(Utilities.debugPosition(doc, blocks[i]));
sb.append(", "); // NOI18N
sb.append(Utilities.debugPosition(doc, blocks[i + 1]));
sb.append(')');
if (i != blocks.length - 1) {
sb.append('\n');
}
}
ret = sb.toString();
}
return ret;
}
public static String debugList(List l) {
String ret;
if (l == null) {
ret = "Null list"; // NOI18N
} else if (l.size() == 0) {
ret = "Empty list"; // NOI18N
} else {
int cnt = l.size();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < cnt; i++) {
sb.append('[');
sb.append(i);
sb.append("]="); // NOI18N
sb.append(l.get(i));
if (i != cnt - 1) {
sb.append('\n');
}
}
ret = sb.toString();
}
return ret;
}
public static String debugIterator(Iterator i) {
String ret;
if (i == null) {
ret = "Null iterator"; // NOI18N
} else if (!i.hasNext()) {
ret = "Empty iterator"; // NOI18N
} else {
StringBuffer sb = new StringBuffer();
int ind = 0;
while (i.hasNext()) {
sb.append('[');
sb.append(ind++);
sb.append("]="); // NOI18N
sb.append(i.next().toString());
if (i.hasNext()) {
sb.append('\n');
}
}
ret = sb.toString();
}
return ret;
}
}
/*
* Log
* 8 Gandalf-post-FCS1.6.1.0 3/8/00 Miloslav Metelka
* 7 Gandalf 1.6 1/13/00 Miloslav Metelka
* 6 Gandalf 1.5 12/28/99 Miloslav Metelka
* 5 Gandalf 1.4 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 4 Gandalf 1.3 10/10/99 Miloslav Metelka
* 3 Gandalf 1.2 9/16/99 Miloslav Metelka
* 2 Gandalf 1.1 9/15/99 Miloslav Metelka
* 1 Gandalf 1.0 9/10/99 Miloslav Metelka
* $
*/